package com.service.impl;

import com.Exception.NormalException.GroupException.UserAlreadyJoinGroupException;
import com.Factory.GroupApplyResultFactory;
import com.Result.GroupApplyResult;
import com.WebSocket.SocketData;
import com.WebSocket.WebSocket;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.entity.*;
import com.mapper.GroupApplyMapper;
import com.mapper.GroupMapper;
import com.mapper.GroupUserMapper;
import com.mapper.UserMapper;
import com.service.GroupApplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author XTC
 * @since 2024-07-10
 */
@Service
public class GroupApplyServiceImpl extends ServiceImpl<GroupApplyMapper, GroupApply> implements GroupApplyService {
    @Autowired
    private GroupApplyMapper groupApplyMapper;

    @Autowired
    private GroupUserMapper groupUserMapper;

    @Autowired
    private GroupMapper groupMapper;

    @Autowired
    private GroupApplyResultFactory groupApplyResultFactory;

    @Override
    public boolean add(GroupApply groupApply) throws UserAlreadyJoinGroupException {
        QueryWrapper<GroupUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", groupApply.getUserId())
                .eq("group_id", groupApply.getGroupId());
        if (!this.groupUserMapper.selectList(queryWrapper).isEmpty()) {
            throw new UserAlreadyJoinGroupException();
        }
        return this.groupApplyMapper.insert(groupApply) > 0;
    }

    @Override
    public boolean acceptApply(Integer groupApplyId) {
        UpdateWrapper<GroupApply> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", groupApplyId)
                .set("status", 1);
        this.groupApplyMapper.update(null, wrapper);

        // 使其他申请失效
        GroupApply groupApply = this.groupApplyMapper.selectById(groupApplyId);
        UpdateWrapper<GroupApply> w2 = new UpdateWrapper<>();
        w2.eq("group_id", groupApply.getGroupId())
                .eq("user_id", groupApply.getUserId())
                .eq("status", 0)
                .ne("id", groupApplyId)
                .set("status", 3);
        this.groupApplyMapper.update(null, w2);
        return true;
    }

    @Override
    public boolean refuseApply(Integer groupApplyId) {
        UpdateWrapper<GroupApply> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", groupApplyId)
                .set("status", 2);
        return this.groupApplyMapper.update(null, wrapper) > 0;
    }

    @Override
    public List<GroupApplyResult> getApplyByGroupList(List<Group> groupList) {
        if(groupList == null || groupList.isEmpty()) {
            return new ArrayList<>();
        }
        QueryWrapper<GroupApply> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("group_id", groupList.stream().map(Group::getId).collect(Collectors.toList()));
        List<GroupApply> applyList = this.groupApplyMapper.selectList(queryWrapper);
        return this.getResultList(applyList);
    }

    private List<GroupApplyResult> getResultList(List<GroupApply> applyList) {
        List<GroupApplyResult> resultList = new ArrayList<>();
        for(GroupApply groupApply : applyList) {
            GroupApplyResult groupApplyResult = this.groupApplyResultFactory.newGroupApplyResult(groupApply);
            resultList.add(groupApplyResult);
        }
        return resultList;
    }

    @Override
    public boolean sendApplyResult(Integer applyId, boolean result) {
        GroupApply groupApply = this.groupApplyMapper.selectById(applyId);
        GroupApplyResult groupApplyResult = this.groupApplyResultFactory.newGroupApplyResult(groupApply);
        SocketData socketData = new SocketData();
        socketData.setType("groupApply");
        socketData.setGroupApply(groupApplyResult);
        WebSocket.sendOneMessage(String.valueOf(groupApply.getUserId()), socketData);
        return true;
    }

    @Override
    public boolean sendGroupApply(GroupApply groupApply) {
        GroupApplyResult groupApplyResult = this.groupApplyResultFactory.newGroupApplyResult(groupApply);
        SocketData socketData = new SocketData();
        socketData.setType("groupApply");
        socketData.setGroupApply(groupApplyResult);
        Group group = this.groupMapper.selectById(groupApply.getGroupId());
        WebSocket.sendOneMessage(String.valueOf(group.getMasterId()), socketData);
        return true;
    }
}
